package com.inspur.edp.udt.designtime.api.json;


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.designtime.api.json.CefNames;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.api.extension.*;

import java.io.IOException;
import java.util.Date;
import java.util.Map;


/**
 * UDT序列化基类
 */
public abstract class UdtSerializer extends JsonSerializer<UnifiedDataTypeDef> {
	protected boolean isFull = true;
	public UdtSerializer(){}
	public UdtSerializer(boolean full){
		isFull = full;
	}

	@Override
	public void serialize(UnifiedDataTypeDef dataType, JsonGenerator writer, SerializerProvider serializers) throws IOException {
		SerializerUtils.writeStartObject(writer);
		SerializerUtils.writePropertyValue(writer, UdtNames.Id, dataType.getId());
		SerializerUtils.writePropertyValue(writer, UdtNames.Code, dataType.getCode());
		SerializerUtils.writePropertyValue(writer, UdtNames.Name, dataType.getName());
		if(isFull||(dataType.getDescription()!=null&&!"".equals(dataType.getDescription())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Description, dataType.getDescription());
		if(isFull||(dataType.getCreator()!=null&&!"".equals(dataType.getCreator())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Creator, dataType.getCreator());
		if(isFull||(dataType.getBeLabel()!=null&&dataType.getBeLabel().size()>0))
			SerializerUtils.writePropertyValue(writer,UdtNames.BeLabel,dataType.getBeLabel());
		writeDateTime(writer, UdtNames.CreatedDate, dataType.getCreatedDate());
		if(isFull||(dataType.getModifier()!=null&&!"".equals(dataType.getModifier())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Modifier, dataType.getModifier());
		writeDateTime(writer, UdtNames.ModifiedDate, dataType.getModifiedDate());
		// 序列化到文件中的是dotnet的AssemblyName
		if(isFull||(dataType.getDotnetAssemblyName()!=null&&!"".equals(dataType.getDotnetAssemblyName())))
			SerializerUtils.writePropertyValue(writer, UdtNames.AssemblyName, dataType.getDotnetAssemblyName());
		if(isFull||!(dataType.getDotnetAssemblyName()+"."+dataType.getCode()).equals(dataType.getI18nResourceInfoPrefix()))
			SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, dataType.getI18nResourceInfoPrefix());

		writeUdtExtendInfo(writer, dataType);
		writePropertyUseTypeInfos(writer, dataType);
		writeValidationInfos(writer, dataType);
		writeExtensions(writer,serializers,dataType);

		SerializerUtils.writeEndObject(writer);
	}

	private void writeExtensions(JsonGenerator writer, SerializerProvider serializers, UnifiedDataTypeDef dataType) {
		if(dataType.getUdtExtensions()==null||dataType.getUdtExtensions().isEmpty())
			return;
		SerializerUtils.writePropertyName(writer,UdtNames.Extensions);
		SerializerUtils.writeStartObject(writer);
		for(Map.Entry<String, BaseUdtExtension> entry:dataType.getUdtExtensions().entrySet())
		{
			SerializerUtils.writePropertyName(writer, entry.getKey());
			UdtExtensionConfig config = UdtExtensionConfigs.getInstance().getExtensionConfig(entry.getKey());
			try {
				BaseUdtExtensionSerializer deserializer= (BaseUdtExtensionSerializer) Class.forName(config.getSerclass()).newInstance();
				deserializer.serialize(entry.getValue(),writer,serializers);
			} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | IOException e) {
				throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_COMMON_0002, config.getSerclass());
			}
		}

		SerializerUtils.writeEndObject(writer);
	}

	private void writeValidationInfos(JsonGenerator writer, UnifiedDataTypeDef dataType) {
		if(isFull||(dataType.getValidations()!=null&&dataType.getValidations().size()>0)){
			SerializerUtils.writePropertyName(writer, UdtNames.ValidationInfos);
			SerializerUtils.WriteStartArray(writer);
			dataType.getValidations().stream().forEach(item -> SerializerUtils.writePropertyValue_Object(writer, item));
			SerializerUtils.WriteEndArray(writer);
		}
	}

	private void writePropertyUseTypeInfos(JsonGenerator writer, UnifiedDataTypeDef dataType) {
		if(isFull||(dataType.getPropertyUseTypeInfos()!=null&&dataType.getPropertyUseTypeInfos().size()>0)){
			SerializerUtils.writePropertyName(writer, UdtNames.PropertyUseTypeInfos);
			SerializerUtils.WriteStartArray(writer);
			dataType.getPropertyUseTypeInfos().forEach((key, value) -> SerializerUtils.writePropertyValue_Object(writer, value));
			SerializerUtils.WriteEndArray(writer);
		}
	}

	protected abstract void writeUdtExtendInfo(JsonGenerator writer, UnifiedDataTypeDef dataType);

	private void writeDateTime(JsonGenerator writer, String propName, Date date) {
		String jsonDate = UdtNames.DateTimeFormat.format(date);
		SerializerUtils.writePropertyValue(writer, propName, jsonDate);
	}
}